/*
 *  Copyright (C) 2011 JiangHongTiao <jjurco.sk_gmail.com>
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package sk.lieskove301.jianghongtiao.liaad.prisoner.strategy;

import java.util.Collections;
import java.util.LinkedList;
import sk.lieskove301.jianghongtiao.liaad.prisoner.agent.Agent;
import java.util.List;
import sk.lieskove301.jianghongtiao.liaad.prisoner.agent.AgentDescComparator;
import sk.lieskove301.jianghongtiao.liaad.prisoner.agent.AgentIncComparator;
import sk.lieskove301.jianghongtiao.liaad.prisoner.agent.BinaryCoBeAgent;
import sk.lieskove301.jianghongtiao.liaad.prisoner.ga.crossover.Crossover;
import sk.lieskove301.jianghongtiao.liaad.prisoner.ga.mutation.Mutation;
import sk.lieskove301.jianghongtiao.liaad.prisoner.ga.selection.Selection;
import sk.lieskove301.jianghongtiao.liaad.prisoner.gene.GeneEnum;
import sk.lieskove301.jianghongtiao.liaad.prisoner.payoff.PayoffValue;
import sk.lieskove301.jianghongtiao.liaad.prisoner.memory.ForgettingEnum;

/**
 * Date of create: May 15, 2011
 *
 * @author JiangHongTiao <jjurco.sk_gmail.com>
 * @version 2011.0515
 */
public class DefaultStrategy implements Strategy {

    private int lambda;
    private int numOfAgents;
    private int renew;
    private ForgettingEnum[] forgetting;
    private PayoffValue payoff;

    /**
     * default strategy of game
     * @param lambda percent of agents will be removed every lap
     */
    public DefaultStrategy(int lambda) {
        this.lambda = lambda;
    }

    public List<Agent> incubator(int numberOfAgents) {
        List<Agent> agents = new LinkedList<Agent>();
        numOfAgents = numberOfAgents;
        //create all type Cooperative/Betray agents
        for(int i=0; i<numOfAgents; i++){
            int g = (~i & 31);
            agents.add(new BinaryCoBeAgent(forgetting[0], payoff, 1, g));
        }
        renew = ((lambda*numberOfAgents)/100);
        return agents;
    }

    public List<Agent> renewPopulation(List<Agent> population, int year) {
        Collections.sort(population, new AgentDescComparator());
        List<Agent> result = new LinkedList<Agent>();
        for(int i=0; i<renew; i++){
//            Agent a = population.get((i % population.size())).copyAgent();
            Agent a = population.get((i % 10)).copyAgent();
            a.setBirthday(year);
            result.add(a);
        }
        return result;
    }

    public List<Agent> genocide(List<Agent> population) {
        Collections.sort(population, new AgentIncComparator());
        List<Agent> result = new LinkedList<Agent>();
        for(int i=0; i<renew; i++){
            result.add(population.get(i));
        }
        return result;
    }

    public ForgettingEnum[] getForgetting() {
        return forgetting;
    }

    public void setForgetting(ForgettingEnum[] forgetting) {
        if(forgetting.length != 1){
            throw new IllegalArgumentException("This strategy supports only one possible forgetting!");
        }
        this.forgetting = forgetting;
    }

    public PayoffValue getPayoff() {
        return payoff;
    }

    public void setPayoff(PayoffValue payoff) {
        this.payoff = payoff;
    }

    public void agentsAmnesia(Agent agent) {
        agent.totalAmnesia();
    }

    public Crossover getCrossover() {
        return null;
    }

    public void setCrossover(Crossover crossover) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Mutation getMutation() {
        return null;
    }

    public void setMutation(Mutation mutation) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Selection getSelection() {
        return null;
    }

    public void setSelection(Selection selection) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public GeneEnum[] getPossibleGenes() {
        return null;
    }

    public void setPossibleGenes(GeneEnum[] possibleGenes) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
